package com.sansan.qiangji.realize.warehouse;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sansan.qiangji.VO.warehouse.pullOrder.PullOrderBoxDetailVO;
import com.sansan.qiangji.VO.warehouse.pullOrder.PullOrderDetailListResultVO;
import com.sansan.qiangji.VO.warehouse.pullOrder.PullOrderDetailVO;
import com.sansan.qiangji.VO.warehouse.stackerTaskOutVO.StackerTaskOutVO;
import com.sansan.qiangji.entity.base.Product;
import com.sansan.qiangji.entity.base.Shelve;
import com.sansan.qiangji.entity.base.Stock;
import com.sansan.qiangji.entity.base.example.ProductExample;
import com.sansan.qiangji.entity.base.example.StockExample;
import com.sansan.qiangji.entity.warehouse.*;
import com.sansan.qiangji.entity.warehouse.example.PullOrderBoxDetailExample;
import com.sansan.qiangji.entity.warehouse.example.PullOrderDetailExample;
import com.sansan.qiangji.enums.ResultEnum;
import com.sansan.qiangji.exception.ServiceException;
import com.sansan.qiangji.form.warehouse.ProductUnbindingStockForm;
import com.sansan.qiangji.form.warehouse.PullOrderDetailAddForm;
import com.sansan.qiangji.form.warehouse.PullOrderDetailEditForm;
import com.sansan.qiangji.form.warehouse.PullOrderDetailListForm;
import com.sansan.qiangji.service.inter.base.ProductService;
import com.sansan.qiangji.service.inter.base.ShelveService;
import com.sansan.qiangji.service.inter.base.StockService;
import com.sansan.qiangji.service.inter.warehouse.*;
import com.sansan.qiangji.task.AsyncTask;
import com.sansan.qiangji.utils.StringUtil;
import com.sansan.qiangji.utils.pageUtils.PageResult;
import com.sansan.qiangji.utils.pageUtils.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PullOrderDetailReal {
    @Autowired
    private PullOrderDetailService pullOrderDetailService;
    @Autowired
    private ProductService productService;
    @Autowired
    private PullOrderBoxDetailService pullOrderBoxDetailService;
    @Autowired
    private StockService stockService;
    @Autowired
    private ShelveService shelveService;
    @Autowired
    private StackerTaskOutService stackerTaskOutService;
    @Autowired
    private StackerTaskInService stackerTaskInService;
    @Autowired
    private StackerTaskMoveService stackerTaskMoveService;

    @Transactional
    public void deletePullOrderDetail(Integer pullOrderDetailId) {
        PullOrderDetail pullOrderDetail = pullOrderDetailService.selectByPrimaryKey(pullOrderDetailId);
        if (pullOrderDetail == null) {
            log.error("【出库单详情删除】出库单详情不存在，pullOrderDetailId={}", pullOrderDetailId);
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_IS_NOT_EXIST);
        }
        PullOrderBoxDetailExample pullOrderBoxDetailExample = new PullOrderBoxDetailExample();
        pullOrderBoxDetailExample.or().andPullOrderDetailCodeEqualTo(pullOrderDetail.getPullOrderDetailCode());
        List<PullOrderBoxDetail> pullOrderBoxDetails = pullOrderBoxDetailService.selectByExample(pullOrderBoxDetailExample);
        if (pullOrderBoxDetails.size()!=0){
            log.error("【出库单详情删除】出库单详情已创建物料箱子，pullOrderDetailId={}", pullOrderDetailId);
            throw new ServiceException(ResultEnum.PULL_ORDER_HAVE_BOX_DETAIL);
        }
        int row = pullOrderDetailService.deleteByPrimaryKey(pullOrderDetailId);
        if (row == 0) {
            log.error("【出库单详情删除】出库单详情删除失败，pullOrderDetailId={}", pullOrderDetailId);
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_DELETE_ERROR);
        }
    }

    @Transactional
    public void addPullOrderDetail(PullOrderDetailAddForm pullOrderDetailAddForm) {
        List<PullOrderDetail> pullOrderDetails = pullOrderDetailService.findByProductCodeOrProductName(pullOrderDetailAddForm.getProductCode(), pullOrderDetailAddForm.getProductName());
        if (pullOrderDetails.size() != 0) {
            log.error("【出库单详情新增】出库详情中已有此物料");
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_PRODUCT_EXIST);
        }
        PullOrderDetail pullOrderDetail = new PullOrderDetail();
        BeanUtils.copyProperties(pullOrderDetailAddForm, pullOrderDetail);
        String code = StringUtil.codeGenerater("pull_detail");
        pullOrderDetail.setPullOrderDetailCode(code);
        pullOrderDetail.setProductPullPace("进行中");

        //查找物料
        ProductExample productExample = new ProductExample();
        productExample.or().andProductCodeEqualTo(pullOrderDetailAddForm.getProductCode()).
                andProductNameEqualTo(pullOrderDetailAddForm.getProductName());
        List<Product> productList = productService.selectByExample(productExample);
        if (productList != null && productList.size() != 0) {
            pullOrderDetail.setProductName(productList.get(0).getProductName());
            pullOrderDetail.setCountBox(productList.get(0).getCountBox());
            pullOrderDetail.setCreateTime(new Date());
        } else {
            log.error("【出库详情新增】找不到该物料");
            throw new ServiceException(ResultEnum.PRODUCT_IS_NOT_EXIST);
        }
        int row = pullOrderDetailService.insert(pullOrderDetail);
        if (row == 0) {
            log.error("【出库单详情新增】出库单详情新增失败");
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_INSERT_ERROR);
        }
    }


    @Transactional
    public void editPullOrderDetail(PullOrderDetailEditForm pullOrderDetailEditForm) {
        /*PullOrderDetail pullOrderDetail = new PullOrderDetail();
        PullOrderDetail order = pullOrderDetailService.selectByPrimaryKey(pullOrderDetailEditForm.getPullOrderDetailId());
        BeanUtils.copyProperties(pullOrderDetailEditForm, order);
        pullOrderDetail.setPullOrderDetailCode(order.getPullOrderDetailCode());
        //查找物料
        ProductExample productExample = new ProductExample();
        productExample.or().andProductCodeEqualTo(pullOrderDetailEditForm.getProductCode());

        List<Product> productList = productService.selectByExample(productExample);
        if (productList != null && productList.size() != 0) {
            pullOrderDetail.setProductName(productList.get(0).getProductName());
            pullOrderDetail.setCountBox(productList.get(0).getCountBox());
        } else {
            log.error("【出库详情修改】找不到该物料");
            throw new ServiceException(ResultEnum.PRODUCT_IS_NOT_EXIST);
        }*/
        PullOrderDetailExample pullOrderDetailExample = new PullOrderDetailExample();
        pullOrderDetailExample.or().andPullOrderDetailCodeEqualTo(pullOrderDetailEditForm.getPullOrderDetailCode());
        List<PullOrderDetail> pullOrderDetails = pullOrderDetailService.selectByExample(pullOrderDetailExample);
        if (pullOrderDetails.size() == 0) {
            log.error("【出库单详情编辑】出库单详情不存在，pullOrderDetailEditForm={}", pullOrderDetailEditForm.toString());
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_IS_NOT_EXIST);
        }
        pullOrderDetails.get(0).setPullOrderCount(pullOrderDetailEditForm.getPullOrderCount());
        int row = pullOrderDetailService.updateByPrimaryKey(pullOrderDetails.get(0));
        if (row == 0) {
            log.error("【出库单详情编辑】出库单详情编辑失败");
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_INSERT_ERROR);
        }
    }

    public PullOrderDetailListResultVO pullOrderDetailList(PullOrderDetailListForm pullOrderDetailListForm) {
        PullOrderDetailExample example = new PullOrderDetailExample();
        int pageNum = pullOrderDetailListForm.getPageNum();
        int pageSize = pullOrderDetailListForm.getPageSize();
        PageHelper.startPage(pageNum, pageSize);
        List<PullOrderDetail> pullOrderDetailList = pullOrderDetailService.selectByExample(example);
        PageResult<PullOrderDetail> pullOrderDetailPageResult = PageUtil.getPageResult(new PageInfo<>(pullOrderDetailList));
        PullOrderDetailListResultVO pullOrderDetailListResultVO = new PullOrderDetailListResultVO();
        BeanUtils.copyProperties(pullOrderDetailPageResult, pullOrderDetailListResultVO);
        List<PullOrderDetailVO> pullOrderDetailVOS = new ArrayList<>();
        for (PullOrderDetail pullOrderDetail : pullOrderDetailPageResult.getContent()) {
            PullOrderDetailVO pullOrderDetailVO = new PullOrderDetailVO();
            BeanUtils.copyProperties(pullOrderDetail, pullOrderDetailVO);
            //查找箱子详情
            PullOrderBoxDetailExample pullOrderBoxDetailExample = new PullOrderBoxDetailExample();
            pullOrderBoxDetailExample.or().andPullOrderDetailCodeEqualTo(pullOrderDetail.getPullOrderDetailCode());
            List<PullOrderBoxDetail> boxDetails = pullOrderBoxDetailService.selectByExample(pullOrderBoxDetailExample);
            List<PullOrderBoxDetailVO> boxDetailVOS = new ArrayList<>();
            for (PullOrderBoxDetail boxDetail : boxDetails) {
                PullOrderBoxDetailVO pullOrderBoxDetailVO = new PullOrderBoxDetailVO();
                BeanUtils.copyProperties(boxDetail, pullOrderDetailVO);
                boxDetailVOS.add(pullOrderBoxDetailVO);
            }
            pullOrderDetailVO.setPullOrderBoxDetailVOS(boxDetailVOS);
            pullOrderDetailVOS.add(pullOrderDetailVO);
        }
        pullOrderDetailListResultVO.setPullOrderDetailVOS(pullOrderDetailVOS);
        return pullOrderDetailListResultVO;
    }

    @Transactional
    public StackerTaskOutVO productUnbindingStock(ProductUnbindingStockForm form) {
        PullOrderDetailExample pullOrderDetailExample = new PullOrderDetailExample();
        if (form.getPullOrderDetailCodeList()!=null && form.getPullOrderDetailCodeList().size() == 0) {
            log.error("【创建出库任务】出库单详情不能为空");
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_CAN_NOT_EMPTY);
        }
        pullOrderDetailExample.or().andPullOrderDetailCodeIn(form.getPullOrderDetailCodeList());
        List<PullOrderDetail> pullOrderDetailList = pullOrderDetailService.selectByExample(pullOrderDetailExample);
        List<PullOrderDetail> pullOrderDetails = new ArrayList<>();
        List<Stock> stocks = new ArrayList<>();
        if (form.getIsAuto()) {
            for (PullOrderDetail pullOrderDetail : pullOrderDetailList) {
                if (pullOrderDetail.getPullOrderCount()!=null && pullOrderDetail.getPullOrderCount()!=0 && pullOrderDetail.getFinishCount() < pullOrderDetail.getPullOrderCount()){
                    StockExample stockExample = new StockExample();
                    StockExample.Criteria criteria = stockExample.createCriteria();
                    criteria.andProductCodeEqualTo(pullOrderDetail.getProductCode());
                    criteria.andProductNameEqualTo(pullOrderDetail.getProductName());
                    criteria.andStockStatusEqualTo("已存放");
                    if (form.getShelveName() != null) {
                        criteria.andShelveNameEqualTo(form.getShelveName());
                    }
                    stocks = stockService.selectByExample(stockExample);
                    if (stocks.size() != 0) {
                        pullOrderDetails.add(pullOrderDetail);
                        break;
                    }
                }
            }
            if (pullOrderDetails.size() == 0) {
                log.error("【创建出库任务】没有可出库的详情单");
                throw new ServiceException(ResultEnum.NOT_PULL_ORDER_DETAIL_CAN_PULL);
            }
        } else if(pullOrderDetailList.size()!=0) {
            pullOrderDetails.add(pullOrderDetailList.get(0));
            StockExample stockExample = new StockExample();
            StockExample.Criteria criteria = stockExample.createCriteria();
            criteria.andProductCodeEqualTo(pullOrderDetails.get(0).getProductCode());
            criteria.andProductNameEqualTo(pullOrderDetails.get(0).getProductName());
            criteria.andStockStatusEqualTo("已存放");
            if (form.getShelveName() != null) {
                criteria.andShelveNameEqualTo(form.getShelveName());
            }
            if (form.getStockId() != null){
                criteria.andStockIdEqualTo(form.getStockId());
            }
            stockExample.setOrderByClause("stock_width desc,stock_height asc");
            stocks = stockService.selectByExample(stockExample);
            if (stocks.size() == 0) {
                log.error("【创建出库任务】物料没有库存");
                throw new ServiceException(ResultEnum.PRODUCT_IS_NO_STOCK);
            }
        } else {
            log.error("【创建出库任务】出库单详情不存在");
            throw new ServiceException(ResultEnum.PULL_ORDER_DETAIL_IS_NOT_EXIST);
        }
        if (pullOrderDetails.get(0).getProductCode() == null || pullOrderDetails.get(0).getProductCode().equals("")) {
            log.error("【创建出库任务】物料编号为空");
            throw new ServiceException(ResultEnum.PRODUCT_CODE_IS_NULL);
        }
        // 得到可出库物料的堆垛机列表，遍历堆垛机列表看哪台堆垛机处于空闲状态，查找空闲堆垛机对应的物料并出库
        List<String> shelveNames = stocks.stream().map(Stock::getShelveName).collect(Collectors.toList());
        List<Shelve> shelves = shelveService.findAllShelve();
        List<String> statusList = new ArrayList<>();
        // 获取入库任务
        statusList.add("中断");
        statusList.add("入库中");
        List<StackerTaskIn> stackerTaskIns = stackerTaskInService.findByStackerTaskStatusIn(statusList);
        // 获取出库任务
        statusList.clear();
        statusList.add("中断");
        statusList.add("出库中");
        List<StackerTaskOut> stackerTaskOuts = stackerTaskOutService.findByStackerTaskStatusIn(statusList);
        // 获取移库任务
        statusList.clear();
        statusList.add("中断");
        statusList.add("移库中");
        List<StackerTaskMove> stackerTaskMoves = stackerTaskMoveService.findByStackerTaskStatusIn(statusList);
        List<Stock> stockList = new ArrayList<>();
        for (String shelveName : shelveNames) {
            List<Shelve> shelveList = shelves.stream().filter(e -> e.getShelveName().equals(shelveName)).collect(Collectors.toList());
            if (shelveList.size() != 0) {
                // 判断堆垛机是否没有出库任务
                if (stackerTaskOuts.stream().anyMatch(e -> e.getStackerName().equals(shelveList.get(0).getStackerName()))) {
                    continue;
                }
                // 判断堆垛机是否有入库任务
                if (stackerTaskIns.stream().anyMatch(e -> e.getStackerName().equals(shelveList.get(0).getStackerName()))) {
                    continue;
                }
                // 判断堆垛机是否有移库任务
                if (stackerTaskMoves.stream().anyMatch(e -> e.getStackerName().equals(shelveList.get(0).getStackerName()))) {
                    continue;
                }
                stockList = stocks.stream().filter(e -> e.getShelveName().equals(shelveName)).collect(Collectors.toList());
                break;
            }
        }
        if (stockList.size() == 0) {
            log.error("【创建出库任务】没有空闲的堆垛机");
            throw new ServiceException(ResultEnum.NO_STACKER_IS_FREE);
        }
        List<Stock> finalStockList = stockList;
        shelves = shelves.stream().filter(e -> e.getShelveName().equals(finalStockList.get(0).getShelveName())).collect(Collectors.toList());
        PullOrderBoxDetail pullOrderBoxDetail = new PullOrderBoxDetail();
        pullOrderBoxDetail.setProductCode(stockList.get(0).getProductCode());
        pullOrderBoxDetail.setProductName(stockList.get(0).getProductName());
        pullOrderBoxDetail.setShelveName(stockList.get(0).getShelveName());
        pullOrderBoxDetail.setShelveWidth(stockList.get(0).getStockWidth());
        pullOrderBoxDetail.setShelveHeight(stockList.get(0).getStockHeight());
        pullOrderBoxDetail.setUnintCount(stockList.get(0).getUnitCount());
        pullOrderBoxDetail.setPullOrderDetailCode(pullOrderDetails.get(0).getPullOrderDetailCode());
        pullOrderBoxDetail.setPullTime(new Date());
        pullOrderBoxDetail.setBoxDetailStatus("未出库");
        String boxDetailCode = StringUtil.codeGenerater("pull_box_detail");
        pullOrderBoxDetail.setBoxDetailCode(boxDetailCode);
        pullOrderBoxDetail.setPullOrderCode(pullOrderDetails.get(0).getPullOrderCode());
        pullOrderBoxDetailService.insert(pullOrderBoxDetail);
        stockList.get(0).setStockStatus("已绑定");
        stockService.updateByPrimaryKey(stockList.get(0));
        StackerTaskOut stackerTaskOut = new StackerTaskOut();
        String taskCode = StringUtil.codeGenerater("pull_task");
        stackerTaskOut.setStackerTaskOutCode(taskCode);
        stackerTaskOut.setPullOrderBoxDetailCode(boxDetailCode);
        stackerTaskOut.setStockHeight(stockList.get(0).getStockHeight());
        stackerTaskOut.setStockWidth(stockList.get(0).getStockWidth());
        stackerTaskOut.setStackerName(shelves.get(0).getStackerName());
        stackerTaskOut.setWarehouseName(shelves.get(0).getWarehouseName());
        stackerTaskOut.setShelveName(shelves.get(0).getShelveName());
        stackerTaskOut.setShelvePlcValue(shelves.get(0).getShelvePlcValue());
        stackerTaskOut.setStackerTaskOutStatus("出库中");
        stackerTaskOut.setStackerTaskOutPace("");
        stackerTaskOut.setPullOrderDetailCode(pullOrderDetails.get(0).getPullOrderDetailCode());
        stackerTaskOut.setProductCode(pullOrderDetails.get(0).getProductCode());
        stackerTaskOut.setPullOrderCode(pullOrderDetails.get(0).getPullOrderCode());
        stackerTaskOutService.addStackerTaskOut(stackerTaskOut);
        StackerTaskOutVO stackerTaskOutVO = new StackerTaskOutVO();
        BeanUtils.copyProperties(stackerTaskOut, stackerTaskOutVO);
        return stackerTaskOutVO;
    }

    @Transactional
    public void stackerTaskOutContinue(String stackerTaskOutCode, String stackerTaskOutPace) {
        StackerTaskOut stackerTaskOut = stackerTaskOutService.findByStackerTaskOutCode(stackerTaskOutCode);
        if (stackerTaskOut == null) {
            log.error("【出库任务继续】堆垛机任务不存在，stackerTaskOutCode={}", stackerTaskOutCode);
            throw new ServiceException(ResultEnum.STACKER_TASK_OUT_NOT_EXIST);
        }
        if (!Arrays.asList(new String[]{"未执行", "取货完成", "放货完成", "出货完成"}).contains(stackerTaskOutPace)) {
            log.error("【出库任务继续】出库进度类型不存在，stackerTaskOutPace={}", stackerTaskOutPace);
            throw new ServiceException(ResultEnum.STACKER_TASK_OUT_PACE_NOT_EXIST);
        }
        if (!stackerTaskOut.getStackerTaskOutStatus().equals("中断")) {
            log.error("【出库任务继续】任务非中断状态，stackerTaskOutCode={}", stackerTaskOutCode);
            throw new ServiceException(ResultEnum.STACKER_TASK_NOT_ERROR);
        }
        List<String> statusList = new ArrayList<>();
        // 获取入库任务
        statusList.add("中断");
        statusList.add("入库中");
        List<StackerTaskIn> stackerTaskIns = stackerTaskInService.findByStackerTaskStatusIn(statusList);
        // 获取出库任务
        statusList.clear();
        statusList.add("中断");
        statusList.add("出库中");
        List<StackerTaskOut> stackerTaskOuts = stackerTaskOutService.findByStackerTaskStatusIn(statusList);
        // 获取移库任务
        statusList.clear();
        statusList.add("中断");
        statusList.add("移库中");
        List<StackerTaskMove> stackerTaskMoves = stackerTaskMoveService.findByStackerTaskStatusIn(statusList);
        // 判断堆垛机是否有移库任务
        if (stackerTaskIns.stream().anyMatch(e -> e.getStackerName().equals(stackerTaskOut.getStackerName()))) {
            log.error("【出库任务继续】堆垛机非空闲");
            throw new ServiceException(ResultEnum.STACKER_IS_NOT_FREE);
        }
        List<StackerTaskOut> stackerTaskOutList = stackerTaskOuts.stream().filter(e -> e.getStackerName().equals(stackerTaskOut.getStackerName())&&!e.getStackerTaskOutCode().equals(stackerTaskOut.getStackerTaskOutCode())).collect(Collectors.toList());
        if (stackerTaskOutList.size() > 0) {
            log.error("【出库任务继续】堆垛机非空闲，stackerTaskOutCode={}", stackerTaskOutCode);
            throw new ServiceException(ResultEnum.STACKER_IS_NOT_FREE);
        }
        // 判断堆垛机是否有移库任务
        if (stackerTaskMoves.stream().anyMatch(e -> e.getStackerName().equals(stackerTaskOut.getStackerName()))) {
            log.error("【出库任务继续】堆垛机非空闲");
            throw new ServiceException(ResultEnum.STACKER_IS_NOT_FREE);
        }
        if (stackerTaskOutPace.equals("未执行")) {
            stackerTaskOut.setStackerTaskOutPace("");
        }
        if (stackerTaskOutPace.equals("取货完成")) {
            stackerTaskOut.setStackerTaskOutPace("取货");
        }
        if (stackerTaskOutPace.equals("放货完成")) {
            stackerTaskOut.setStackerTaskOutPace("放货");
        }
        if (stackerTaskOutPace.equals("出货完成")) {
            stackerTaskOut.setStackerTaskOutPace("出货");
        }
        stackerTaskOut.setStackerTaskOutStatus("出库中");
        stackerTaskOutService.updateStackerTaskOut(stackerTaskOut);
    }
}
